package com.rsk.aop.config;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import com.rsk.aop.ParamCheck;
import com.rsk.aop.exception.ParamIsNullException;
import com.rsk.aop.exception.ParamLengthException;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

@Component
@Aspect
public class ParamCheckAop {

    /**
     * 定义有一个切入点，范围为web包下的类
     */
    @Pointcut("execution(public * com.rsk.api..*.*(..))")
    public void checkParam() {
    }

    @Before("checkParam()")
    public void doBefore(JoinPoint joinPoint) {
    }

    /**
     * 检查参数是否为空
     */
    @Around("checkParam()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

        MethodSignature signature = ((MethodSignature) pjp.getSignature());
        //得到拦截的方法
        Method method = signature.getMethod();
        //获取方法参数注解，返回二维数组是因为某些参数可能存在多个注解
        Annotation[][] parameterAnnotations = method.getParameterAnnotations();
        if (parameterAnnotations == null || parameterAnnotations.length == 0) {
            return pjp.proceed();
        }
        //获取方法参数名
        String[] paramNames = signature.getParameterNames();
        //获取参数值
        Object[] paranValues = pjp.getArgs();
        //获取方法参数类型
        Class<?>[] parameterTypes = method.getParameterTypes();
        for (int i = 0; i < parameterAnnotations.length; i++) {
            for (int j = 0; j < parameterAnnotations[i].length; j++) {
                //如果该参数前面的注解是ParamCheck的实例，并且notNull()=true,则进行非空校验
                if (parameterAnnotations[i][j] != null && parameterAnnotations[i][j] instanceof ParamCheck && ((ParamCheck) parameterAnnotations[i][j]).notNull()) {
                    paramIsNull(paramNames[i], paranValues[i], parameterTypes[i] == null ? null : parameterTypes[i].getName());
                }
              //如果该参数前面的注解是ParamCheck的实例，并且notNull()=true,则进行非空校验
                if (parameterAnnotations[i][j] != null && parameterAnnotations[i][j] instanceof ParamCheck && ((ParamCheck) parameterAnnotations[i][j]).length().length>0) {
                	int[] validateValue = ((ParamCheck) parameterAnnotations[i][j]).length();
                	paramLength(paramNames[i], paranValues[i], parameterTypes[i] == null ? null : parameterTypes[i].getName(),validateValue);
                }
            }
        }
        return pjp.proceed();
    }

    /**
     * 在切入点return内容之后切入内容（可以用来对处理返回值做一些加工处理）
     *
     * @param joinPoint
     */
    @AfterReturning("checkParam()")
    public void doAfterReturning(JoinPoint joinPoint) {
    }

    /**
     * 参数非空校验
     */
    private void paramIsNull(String paramName, Object value, String parameterType) {
        if (value == null || "".equals(value.toString().trim())) {
            throw new ParamIsNullException(paramName, parameterType);
        }
    }
    
    /**
     * 参数长度校验
     */
    private void paramLength(String paramName, Object value, String parameterType, int[] validateValue) {
        if (value != null && !"".equals(value.toString().trim())) {
        	String v = String.valueOf(value);
        	int minLength = validateValue[0];
        	int maxLength = validateValue[1];
        	int vLength = v.length();
        	if(vLength<minLength||vLength>maxLength){
        		throw new ParamLengthException(paramName, parameterType, minLength, maxLength);
        	}
        }else{
        	throw new ParamIsNullException(paramName, parameterType);
        }
    }

}
